//-----------------------------------------------------------------------------
//  File          : printmw.c
//  Module        :
//  Description   : Include printf function for midware.
//  Author        : Lewis
//  Notes         :
//
// ============================================================================
// | Naming conventions                                                       |
// | ~~~~~~~~~~~~~~~~~~                                                       |
// |         Struct/Array : Leading s                                         |
// |             Constant : Leading K                                         |
// |      Global Variable : Leading g  (variable use outside one C file)      |
// |                                                                          |
// |   BYTE( 8 Bits) size : Leading b                                         |
// |   CHAR( 8 Bits) size : Leading c                                         |
// |   WORD(16 Bits) size : Leading w                                         |
// |  DWORD(32 Bits) size : Leading d                                         |
// |    int(32 Bits) size : Leading i                                         |
// | DDWORD(64 Bits) size : Leading dd                                        |
// |              Pointer : Leading p                                         |
// |                                                                          |
// |    Function argument : Leading a                                         |
// |       Local Variable : All lower case                                    |
// |                                                                          |
// | Examples:                                                                |
// |                Array : Leading s, (sb = arrary of byte, etc)             |
// |              Pointer : Leading p, (pb = pointer of byte, etc)            |
// ============================================================================
//
//  Date          Who         Action
//  ------------  ----------- -------------------------------------------------
//  01 Apr  2009  Lewis       Initial Version.
//-----------------------------------------------------------------------------
#include <stdarg.h>
#include "system.h"
#ifdef SUPPORT_128X64
#include "midware.h"
#endif

//-----------------------------------------------------------------------------
//  Defines
//-----------------------------------------------------------------------------
#define PAD_RIGHT 1
#define PAD_ZERO 2
#define PRINT_BUF_LEN 12


//*****************************************************************************
//  Function        : PrintC
//  Description     : PrintC function for Midware.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
static void PrintC(int c)
{
#ifdef SUPPORT_128X64
  PutCharMW(c);
#else
  os_disp_putc(c);
#endif
}
//*****************************************************************************
//  Function        : PrintS
//  Description     : PrintS function for Midware.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
static int PrintS(const unsigned char *string, int width, int pad)
{
  register int pc = 0, padchar = ' ';

  if (width > 0) {
    register int len = 0;
    register const unsigned char *ptr;
    for (ptr = string; *ptr; ++ptr) ++len;
    if (len >= width) width = 0;
    else width -= len;
    if (pad & PAD_ZERO) padchar = '0';
  }
  if (!(pad & PAD_RIGHT)) {
    for ( ; width > 0; --width) {
      PrintC(padchar);
      ++pc;
    }
  }
  for ( ; *string ; ++string) {
    PrintC(*string);
    ++pc;
  }
  for ( ; width > 0; --width) {
    PrintC(padchar);
    ++pc;
  }

  return pc;
}
//*****************************************************************************
//  Function        : PrintI
//  Description     : PrintI function for Midware.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
static int PrintI(int i, int b, int sg, int width, int pad, int letbase)
{
  unsigned char print_buf[PRINT_BUF_LEN];
  register unsigned char *s;
  register int t, neg = 0, pc = 0;
  register unsigned int u = i;

  if (i == 0) {
    print_buf[0] = '0';
    print_buf[1] = '\0';
    return PrintS(print_buf, width, pad);
  }

  if (sg && b == 10 && i < 0) {
    neg = 1;
    u = -i;
  }

  s = print_buf + PRINT_BUF_LEN-1;
  *s = '\0';

  while (u) {
    t = u % b;
    if ( t >= 10 )
      t += letbase - '0' - 10;
    *--s = t + '0';
    u /= b;
  }

  if (neg) {
    if ( width && (pad & PAD_ZERO) ) {
      PrintC('-');
      ++pc;
      --width;
    }
    else {
      *--s = '-';
    }
  }

  return pc + PrintS(s, width, pad);
}
//*****************************************************************************
//  Function        : PrintMW
//  Description     : Print function for Midware.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
static int PrintMW(const unsigned char *format, va_list args)
{
  register int width, pad;
  register int pc = 0;
  unsigned char scr[2];

  for (; *format != 0; ++format) {
    if (*format == '%') {
      ++format;
      width = pad = 0;
      if (*format == '\0') break;
      if (*format == '%') goto out;
      if (*format == '-') {
        ++format;
        pad = PAD_RIGHT;
      }
      while (*format == '0') {
        ++format;
        pad |= PAD_ZERO;
      }
      for ( ; *format >= '0' && *format <= '9'; ++format) {
        width *= 10;
        width += *format - '0';
      }
      if ( *format == 's' ) {
        register char *s = (char *)va_arg( args, int );
        pc += PrintS(s?s:"(null)", width, pad);
        continue;
      }
      if ( *format == 'd' ) {
        pc += PrintI(va_arg( args, int ), 10, 1, width, pad, 'a');
        continue;
      }
      if ( *format == 'x' ) {
        pc += PrintI(va_arg( args, int ), 16, 0, width, pad, 'a');
        continue;
      }
      if ( *format == 'X' ) {
        pc += PrintI(va_arg( args, int ), 16, 0, width, pad, 'A');
        continue;
      }
      if ( *format == 'u' ) {
        pc += PrintI(va_arg( args, int ), 10, 0, width, pad, 'a');
        continue;
      }
      if ( *format == 'c' ) {
        /* char are converted to int then pushed on the stack */
        scr[0] = (unsigned char)va_arg( args, int );
        scr[1] = '\0';
        pc += PrintS(scr, width, pad);
        continue;
      }
    }
    else {
out:
      PrintC(*format);
      ++pc;
    }
  }
  va_end( args );
  return pc;
}
//*****************************************************************************
//  Function        : PrintfMW
//  Description     : Printf function for Midware.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
int printfmw(const unsigned char *aFormat, ...)
{
  va_list args;
  va_start(args, aFormat);

  if (!os_app_search_id(K_MidID))
    return 0;

  return PrintMW(aFormat, args);
}
